package com.ella.config;
import com.ella.common.constants.JwtConstant;
import com.ella.common.security.filter.JwtAuthenticationTokenFilter;
import com.ella.common.security.handler.AuthenticationEntryPointImpl;
import com.ella.common.security.handler.LogoutSuccessHandlerImpl;
import com.ella.common.security.service.UserDetailsServiceImpl;
import nonapi.io.github.classgraph.types.Parser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解配置的功能 @PreAuthorize注解才可以使用
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Resource
	private UserDetailsServiceImpl userDetailsService;

	/**
	 * 认证失败处理类
	 */
	@Resource
	private AuthenticationEntryPointImpl unauthorizedHandler;

	/**
	 * token认证过滤器
	 */
    @Resource
	private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Resource
	private LogoutSuccessHandlerImpl logoutSuccessHandler;

	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Override
	protected AuthenticationManager authenticationManager() throws Exception {
		return super.authenticationManager();
	}

	//PasswordEncoder是一个密码解析器强散列哈希加密实现

	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}


	/**
	 * 自定义AuthenticationManage 的
	 */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		    http
				//配置跨域
				.cors()
				.and()
				//关闭csrf
				.csrf().disable()
				//不通过Session获取SecurityContext
				.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
				.and()
				.authorizeRequests()
				// 对于登录接口 允许匿名访问 permitAll()方法只能在前面出现authorizeRequests()时才能使用的
				.antMatchers(JwtConstant.URL_WHITELIST).permitAll()
				//这句话表示请求这个接口需要有sys:demo:hello这个权限才嗯那个访问
				.antMatchers("/sys-user/list").hasAnyAuthority("sys:demo:hello")
				// 除上面外的所有请求全部需要鉴权认证
				.anyRequest().authenticated();
		        //请求这些路径的用户必须拥有common角色权限
		        //.and().authorizeRequests().antMatchers("/sys-user/**","/sys-index/**").hasRole("common");
				// todo 当用户推出登录时
			http.
		        logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
			// TODO 这句话是什么意思
			http.antMatcher("/sys-verity/demo1").anonymous()
				 .and()
				// TODO 这个地方为啥放行没有成功
				.mvcMatcher("/sys-verity/demo2").anonymous();
				/*
				给一些没有注册的用户或者没有登录的用户分配一个角色,
				他们大部分有浏览网页的权限，但是没有购买,评价...的权限
				.and()
				.anonymous()
				.authorities("ROLE_ANONYMOUS");*/

		//对session的禁用->无状态
		    http
				.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS)

				//添加token权限校验过滤器的位置
				.and()
				.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
				//添加token认证异常处理器
		    http.exceptionHandling().authenticationEntryPoint(unauthorizedHandler);

				//添加授权失败处理器

	}

}
